/* 
 * Copyright (C) 2012 UTSChedule
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package utsc.apps.utschedule.classes;

/**
 * This class extends from {@link GenericGrade} and adds some extra utility
 * methods to calculate the grade according to UTSC's standard.
 * 
 * @author
 * 
 */
public class UofTGrade extends GenericGrade {

	private String _letterGrade = null;
	private static final String DEFAULT_LETTER_GRADE="N/A";
	private double _gpa = -1.0;

	public UofTGrade(double _marks, double _total, double _weight)
			throws IllegalArgumentException {
		super(_marks, _total, _weight);
	}

	public UofTGrade(double _marks) throws IllegalArgumentException {
		super(_marks);
	}

	/**
	 * The letters that represent the grade (from A+ all the way to F).
	 */
	public static final String[] LETTER_GRADES = { "A+", "A", "A-", "B+", "B",
			"B-", "C+", "C", "C-", "D+", "D", "D-", "F" };

	/**
	 * The grade value ranges that represent the letter grades.
	 */
	public static final double[][] LETTER_GRADES_VALUES = { { 90, 100 },
			{ 85, 90 }, { 80, 84 }, { 77, 79 }, { 73, 76 }, { 70, 72 },
			{ 67, 69 }, { 63, 66 }, { 60, 62 }, { 57, 59 }, { 53, 56 },
			{ 50, 52 }, { 0, 49 } };

	/**
	 * The gpa values that represent the letter grades.
	 */
	public static final double[] GPA_VALUES = { 4.0, 4.0, 3.7, 3.3, 3.0, 2.7,
			2.3, 2.0, 1.7, 1.3, 1.0, 0.7, 0.0 };

	/**
	 * Calculates the gpa based on the grade info provided.
	 * @return the calculated gpa
	 */
	public double get_GPA() {
		if (_gpa < 0) {
			double marks = this.calculatePercentage();
			double[] gradeGroup;
			for (int i = 0; i < GPA_VALUES.length; i++) {
				gradeGroup = LETTER_GRADES_VALUES[i];
				if (marks >= gradeGroup[0] && marks <= gradeGroup[1]) {
					_gpa = GPA_VALUES[i];
				}
			}
		}
		return _gpa;
	}
	
	/**
	 * Returns the minimum grade that the given gpa requires.
	 * @param gpa
	 * @return the minimum grade
	 */
	public static double getMinGrade(double gpa) {
		double gpaValue, nextGpaValue;
		int length=GPA_VALUES.length;
		for (int i = 0; i < length-1; i++) {
			gpaValue = GPA_VALUES[i];
			nextGpaValue=GPA_VALUES[i+1];
			if (gpa > nextGpaValue && gpa <= gpaValue) {
				return LETTER_GRADES_VALUES[i][0];
			}
		}
		return 0;
	}
	
	/**
	 * Returns the letter grade of the grade data provided.
	 * @return the letter grade
	 */
	public String get_letterGrade() {
		if (_letterGrade == null) {
			double marks = this.calculatePercentage();
			double[] gradeGroup;
			for (int i = 0; i < LETTER_GRADES_VALUES.length; i++) {
				gradeGroup = LETTER_GRADES_VALUES[i];
				if (marks >= gradeGroup[0] && marks <= gradeGroup[1]) {
					_letterGrade = LETTER_GRADES[i];
				}
			}
			if (_letterGrade==null) {
				_letterGrade=DEFAULT_LETTER_GRADE;
			}
		}
		return _letterGrade;
	}

	public void set_letterGrade(String _letterGrade) {
		this._letterGrade = _letterGrade;
	}
	
	@Override
	public String toString() {
		return Double.toString(this.get_marks())+" / "+Double.toString(this.get_total())+" ("+get_letterGrade()+")";
	}
	
	public String toShortString(){
		return Double.toString(this.get_marks())+" / "+Double.toString(this.get_total());
	}
	
	public String toMarkString(){
		return Double.toString(this.get_marks())+" "+get_letterGrade();
	}
	
	public String toPercentageString(){
		return Double.toString(this.calculatePercentage())+"% "+get_letterGrade();
	}
	
	@Override
	public double calculatePercentage() {
		this._letterGrade=null;
		this._gpa=-1.0;
		return super.calculatePercentage();
	}

}
